package com.bupt.hotel.hvac.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.bupt.hotel.hvac.mapper.BillMapper;
import com.bupt.hotel.hvac.mapper.DetailRecordMapper;
import com.bupt.hotel.hvac.model.entity.Bill;
import com.bupt.hotel.hvac.model.entity.DetailRecord;
import com.bupt.hotel.hvac.model.entity.RoomState;
import com.bupt.hotel.hvac.model.enums.FanSpeed;
import com.bupt.hotel.hvac.model.vo.BillVO;
import com.bupt.hotel.hvac.model.vo.DetailRecordVO;
import com.bupt.hotel.hvac.model.vo.RoomStatisticsVO;
import com.bupt.hotel.hvac.model.vo.StatisticsReportVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 计费服务
 * 负责生成账单、详单和统计报表
 */
@Slf4j
@Service
public class BillingService {

    private final BillMapper billMapper;
    private final DetailRecordMapper detailRecordMapper;

    public BillingService(BillMapper billMapper, DetailRecordMapper detailRecordMapper) {
        this.billMapper = billMapper;
        this.detailRecordMapper = detailRecordMapper;
        log.info("计费服务初始化完成");
    }

    /**
     * 生成账单
     */
    @Transactional
    public BillVO generateBill(RoomState roomState, LocalDateTime checkInTime, LocalDateTime checkOutTime) {
        // 创建账单
        Bill bill = new Bill();
        bill.setRoomId(roomState.getRoomId());
        bill.setCheckInTime(checkInTime);
        bill.setCheckOutTime(checkOutTime);
        bill.setTotalCost(roomState.getTotalCost());
        bill.setTotalPowerConsumption(roomState.getTotalPowerConsumption());
        bill.setTotalServiceDuration(0); // 将在后面计算
        bill.setCreateTime(LocalDateTime.now());

        billMapper.insert(bill);

        // 查询该房间的所有详单记录
        List<DetailRecord> detailRecords = detailRecordMapper.selectList(
                new LambdaQueryWrapper<DetailRecord>()
                        .eq(DetailRecord::getRoomId, roomState.getRoomId())
                        .orderByAsc(DetailRecord::getTimestamp));

        // 更新详单记录的billId
        for (DetailRecord record : detailRecords) {
            record.setBillId(bill.getId());
        }
        detailRecords.forEach(detailRecordMapper::updateById);

        // 计算总服务时长
        int totalDuration = detailRecords.stream()
                .filter(r -> r.getDuration() != null && r.getDuration() > 0)
                .mapToInt(DetailRecord::getDuration)
                .sum();

        bill.setTotalServiceDuration(totalDuration);
        billMapper.updateById(bill);

        // 转换为VO
        BillVO billVO = convertToBillVO(bill, detailRecords);

        log.info("生成账单成功 - 房间: {}, 总费用: {}元, 总耗电: {}度",
                roomState.getRoomId(), bill.getTotalCost(), bill.getTotalPowerConsumption());

        return billVO;
    }

    /**
     * 获取账单
     */
    public BillVO getBill(String roomId) {
        Bill bill = billMapper.selectOne(
                new LambdaQueryWrapper<Bill>()
                        .eq(Bill::getRoomId, roomId)
                        .orderByDesc(Bill::getCreateTime)
                        .last("LIMIT 1"));

        if (bill == null) {
            return null;
        }

        List<DetailRecord> detailRecords = detailRecordMapper.selectList(
                new LambdaQueryWrapper<DetailRecord>()
                        .eq(DetailRecord::getBillId, bill.getId())
                        .orderByAsc(DetailRecord::getTimestamp));

        return convertToBillVO(bill, detailRecords);
    }

    /**
     * 获取所有账单
     */
    public List<BillVO> getAllBills() {
        List<Bill> bills = billMapper.selectList(
                new LambdaQueryWrapper<Bill>()
                        .orderByDesc(Bill::getCreateTime));

        return bills.stream()
                .map(bill -> {
                    List<DetailRecord> detailRecords = detailRecordMapper.selectList(
                            new LambdaQueryWrapper<DetailRecord>()
                                    .eq(DetailRecord::getBillId, bill.getId())
                                    .orderByAsc(DetailRecord::getTimestamp));
                    return convertToBillVO(bill, detailRecords);
                })
                .collect(Collectors.toList());
    }

    /**
     * 生成统计报表
     */
    public StatisticsReportVO generateStatisticsReport(Long startTime, Long endTime) {
        LocalDateTime startDateTime = LocalDateTime.ofInstant(
                new Date(startTime).toInstant(), ZoneId.systemDefault());
        LocalDateTime endDateTime = LocalDateTime.ofInstant(
                new Date(endTime).toInstant(), ZoneId.systemDefault());

        // 查询时间范围内的账单
        List<Bill> bills = billMapper.selectList(
                new LambdaQueryWrapper<Bill>()
                        .ge(Bill::getCheckInTime, startDateTime)
                        .le(Bill::getCheckOutTime, endDateTime));

        StatisticsReportVO report = new StatisticsReportVO();
        report.setStartTime(startTime);
        report.setEndTime(endTime);

        if (bills.isEmpty()) {
            report.setTotalRooms(0);
            report.setTotalServiceRequests(0);
            report.setTotalCost(BigDecimal.ZERO);
            report.setTotalPowerConsumption(BigDecimal.ZERO);
            report.setAverageCostPerRoom(BigDecimal.ZERO);
            report.setRoomStatistics(new ArrayList<>());
            report.setFanSpeedDistribution(Map.of("low", 0, "medium", 0, "high", 0));
            return report;
        }

        // 计算总计数据
        Set<String> uniqueRooms = bills.stream()
                .map(Bill::getRoomId)
                .collect(Collectors.toSet());

        BigDecimal totalCost = bills.stream()
                .map(Bill::getTotalCost)
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        BigDecimal totalPowerConsumption = bills.stream()
                .map(Bill::getTotalPowerConsumption)
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        // 计算服务请求总数
        int totalServiceRequests = 0;
        Map<String, Integer> fanSpeedDistribution = new HashMap<>();
        fanSpeedDistribution.put("low", 0);
        fanSpeedDistribution.put("medium", 0);
        fanSpeedDistribution.put("high", 0);

        // 按房间统计
        Map<String, RoomStatisticsVO> roomStatsMap = new HashMap<>();

        for (Bill bill : bills) {
            List<DetailRecord> detailRecords = detailRecordMapper.selectList(
                    new LambdaQueryWrapper<DetailRecord>()
                            .eq(DetailRecord::getBillId, bill.getId()));

            // 统计服务请求次数
            long serviceCount = detailRecords.stream()
                    .filter(r -> r.getAction().contains("开始送风"))
                    .count();
            totalServiceRequests += serviceCount;

            // 统计风速分布
            for (DetailRecord record : detailRecords) {
                if (record.getFanSpeed() != null) {
                    String speed = record.getFanSpeed().getValue();
                    fanSpeedDistribution.put(speed, fanSpeedDistribution.get(speed) + 1);
                }
            }

            // 按房间统计
            RoomStatisticsVO roomStats = roomStatsMap.get(bill.getRoomId());
            if (roomStats == null) {
                roomStats = new RoomStatisticsVO();
                roomStats.setRoomId(bill.getRoomId());
                roomStats.setServiceCount(0);
                roomStats.setTotalCost(BigDecimal.ZERO);
                roomStats.setTotalPowerConsumption(BigDecimal.ZERO);
                roomStats.setTotalServiceDuration(0);
                roomStats.setAverageTemp(BigDecimal.ZERO);
                roomStats.setMostUsedFanSpeed(FanSpeed.MEDIUM);
                roomStatsMap.put(bill.getRoomId(), roomStats);
            }

            roomStats.setServiceCount(roomStats.getServiceCount() + (int) serviceCount);
            roomStats.setTotalCost(roomStats.getTotalCost().add(bill.getTotalCost()));
            roomStats.setTotalPowerConsumption(
                    roomStats.getTotalPowerConsumption().add(bill.getTotalPowerConsumption()));
            roomStats.setTotalServiceDuration(roomStats.getTotalServiceDuration() + bill.getTotalServiceDuration());

            // 计算平均温度
            List<DetailRecord> tempRecords = detailRecords.stream()
                    .filter(r -> r.getCurrentTemp() != null && r.getCurrentTemp().compareTo(BigDecimal.ZERO) > 0)
                    .collect(Collectors.toList());

            if (!tempRecords.isEmpty()) {
                BigDecimal avgTemp = tempRecords.stream()
                        .map(DetailRecord::getCurrentTemp)
                        .reduce(BigDecimal.ZERO, BigDecimal::add)
                        .divide(new BigDecimal(tempRecords.size()), 2, RoundingMode.HALF_UP);
                roomStats.setAverageTemp(avgTemp);
            }

            // 找出最常使用的风速
            Map<FanSpeed, Integer> speedDuration = new HashMap<>();
            for (DetailRecord record : detailRecords) {
                if (record.getFanSpeed() != null && record.getDuration() != null) {
                    speedDuration.put(record.getFanSpeed(),
                            speedDuration.getOrDefault(record.getFanSpeed(), 0) + record.getDuration());
                }
            }

            if (!speedDuration.isEmpty()) {
                FanSpeed mostUsed = speedDuration.entrySet().stream()
                        .max(Map.Entry.comparingByValue())
                        .map(Map.Entry::getKey)
                        .orElse(FanSpeed.MEDIUM);
                roomStats.setMostUsedFanSpeed(mostUsed);
            }
        }

        report.setTotalRooms(uniqueRooms.size());
        report.setTotalServiceRequests(totalServiceRequests);
        report.setTotalCost(totalCost);
        report.setTotalPowerConsumption(totalPowerConsumption);
        report.setAverageCostPerRoom(totalCost.divide(new BigDecimal(uniqueRooms.size()), 2, RoundingMode.HALF_UP));
        report.setRoomStatistics(new ArrayList<>(roomStatsMap.values()));
        report.setFanSpeedDistribution(fanSpeedDistribution);

        log.info("生成统计报表成功 - 时间范围: {} 到 {}, 房间数: {}, 总费用: {}元",
                startDateTime, endDateTime, uniqueRooms.size(), totalCost);

        return report;
    }

    /**
     * 转换为BillVO
     */
    private BillVO convertToBillVO(Bill bill, List<DetailRecord> detailRecords) {
        BillVO vo = new BillVO();
        vo.setRoomId(bill.getRoomId());
        vo.setCheckInTime(bill.getCheckInTime().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
        vo.setCheckOutTime(bill.getCheckOutTime().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
        vo.setTotalCost(bill.getTotalCost());
        vo.setTotalPowerConsumption(bill.getTotalPowerConsumption());
        vo.setTotalServiceDuration(bill.getTotalServiceDuration());

        List<DetailRecordVO> detailVOs = detailRecords.stream()
                .map(this::convertToDetailRecordVO)
                .collect(Collectors.toList());
        vo.setDetailRecords(detailVOs);

        return vo;
    }

    /**
     * 转换为DetailRecordVO
     */
    private DetailRecordVO convertToDetailRecordVO(DetailRecord record) {
        DetailRecordVO vo = new DetailRecordVO();
        vo.setTimestamp(record.getTimestamp().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli());
        vo.setAction(record.getAction());
        vo.setFanSpeed(record.getFanSpeed());
        vo.setTargetTemp(record.getTargetTemp());
        vo.setCurrentTemp(record.getCurrentTemp());
        vo.setPowerConsumption(record.getPowerConsumption());
        vo.setCost(record.getCost());
        vo.setDuration(record.getDuration());
        return vo;
    }
}
